home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / editors / eedraw / src / eep / eelibs1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-29  |  19.1 KB  |  596 lines

  1. /*****************************************************************************
  2. *   Module to handle libraries (first part - file and io).             *
  3. *                                         *
  4. * Written by:  Gershon Elber            IBM PC Ver 1.0,    Oct. 1989    *
  5. *****************************************************************************/
  6.  
  7. #include <math.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <time.h>
  11.  
  12. #ifdef __MSDOS__
  13. #include <stdlib.h>
  14. #include <conio.h>
  15. #include <dos.h>
  16. #include <dir.h>
  17. #include <alloc.h>
  18. #else
  19. #include <ctype.h>
  20. char *strupr(char *s);
  21. char *strlwr(char *s);
  22. #endif /* __MSDOS__ */
  23.  
  24. #include "program.h"
  25. #include "priorque.h"
  26. #include "eelibs.h"
  27. #include "eelibsl.h"
  28. #include "eeredraw.h"
  29. #include "igraph.h"
  30.  
  31. LibraryStruct *LibraryList = NULL;        /* All part libs are saved here. */
  32.  
  33. static char *GetLine(FILE *f, char *Line, int *LineNum);
  34. static PriorQue *LoadLibraryAux(FILE *f, int *NumOfParts);
  35. static char *GetPinsEntry(FILE *f, char *Line, int *LineNum, int NumOfPins);
  36. static int *GetMultiEntry(FILE *f, char *Line, int *LineNum, int NumOfUnits,
  37.                             int PinsPerUnit);
  38. static LibraryDrawEntryStruct *GetDrawEntry(FILE *f, char *Line, int *LineNum,
  39.             BooleanType *HasLines, LibraryEntryStruct *LibEnrty);
  40. static void UpdateBBox(LibraryEntryStruct *LibEntry, int x, int y);
  41. static LibraryStruct *FindLibrary(char *Name);
  42.  
  43. /*****************************************************************************
  44. * Routine to load the given library name. FullLibName should hold full path  *
  45. * of file name to open, while LibName should hold only its name.         *
  46. *****************************************************************************/
  47. void LoadLibraryName(char *FullLibName, char *LibName)
  48. {
  49.     int NumOfParts;
  50.     char Line[LINE_LEN_SHORT];
  51.     FILE *f;
  52.     LibraryStruct *NewLib;
  53.     PriorQue *Entries;
  54.  
  55.     /* Dont reload same library twice: */
  56.     if (FindLibrary(LibName) != NULL) return;
  57.  
  58.     f = fopen(FullLibName, "rt");
  59.     if (f == NULL) {
  60.     sprintf(Line, "Failed to open library \"%s\".\n", FullLibName);
  61.     FatalError(Line);
  62.     }
  63.  
  64.     fprintf(stderr, "Reading library \"%s\".\n", FullLibName);
  65.  
  66.     if ((Entries = LoadLibraryAux(f, &NumOfParts)) != NULL) {
  67.     NewLib = (LibraryStruct *) MyMalloc(sizeof(LibraryStruct));
  68.     NewLib -> Entries = Entries;
  69.     NewLib -> NumOfParts = NumOfParts;
  70.     strcpy(NewLib -> Name, LibName);
  71.     NewLib -> Pnext = LibraryList;
  72.     LibraryList = NewLib;
  73.     }
  74.     fclose(f);
  75. }
  76.  
  77. /*****************************************************************************
  78. * Routine to load all libraries specified lin LoadLibraryList which assumes  *
  79. * to hold names of libraries to load, seperated by commas and with no lib    *
  80. * extension. Note we dont use strtok inside the loop as LoadLibraryName uses *
  81. * it internally.                                 *
  82. *****************************************************************************/
  83. void LoadLibraries(char *LoadLibraryList)
  84. {
  85.     char *p,*pcc, *NextLibName, Name[LINE_LEN_SHORT],
  86.     *LibName = LoadLibraryList;
  87.  
  88.     if (!strtok(LibName, "\n\r") || strlen(LibName) == 0) return;
  89.  
  90.     do {
  91.     if ((NextLibName = strchr(LibName, ',')) != NULL) {
  92.         NextLibName[0] = 0;
  93.         NextLibName = &NextLibName[1];
  94.     }
  95.     strlwr(LibName);
  96.     strcpy(Name, LibName);
  97.     if ((p = strrchr(Name, '.')) != NULL && strlen(p) < 5) *p = 0;
  98.     strcat(Name, ".lib");
  99.     if ((p = searchpath(Name)) == NULL) {
  100.         char Line[LINE_LEN];
  101.  
  102.      
  103.         pcc = getenv("EEDLIB");
  104.         if(pcc==NULL){
  105.             fprintf(stderr,"EEDRAW: Libraries not found in search path, and EEDLIB not set\n");
  106.             exit(1);
  107.         }
  108.         sprintf(Line,"%s\\%s",pcc,Name);
  109.         
  110.         p=Line;
  111.     }
  112.  
  113.     LoadLibraryName(p, LibName);
  114.  
  115.     LibName = NextLibName;
  116.     }
  117.     while (LibName != NULL);
  118. }
  119.  
  120. /*****************************************************************************
  121. * Routine to read one line from given file.                     *
  122. *****************************************************************************/
  123. static char *GetLine(FILE *f, char *Line, int *LineNum)
  124. {
  125.     do {
  126.     if (fgets(Line, LINE_LEN - 1, f) == NULL) return NULL;
  127.     ++*LineNum;
  128.     }
  129.     while (Line[0] == '#' || Line[0] == '\n' || Line[0] == 0);
  130.  
  131.     return Line;
  132. }
  133.  
  134. /*****************************************************************************
  135. * Routine to compare two LibraryEntryStruct for the PriorQue module.         *
  136. * Comparison is based on Part name.                         *
  137. *****************************************************************************/
  138. int LibraryEntryCompare(LibraryEntryStruct *LE1,
  139.             LibraryEntryStruct *LE2)
  140. {
  141.     return strcmp(LE1 -> Name, LE2 -> Name);
  142. }
  143.  
  144. /*****************************************************************************
  145. * Routine to load a library from given open file.                 *
  146. *****************************************************************************/
  147. static PriorQue *LoadLibraryAux(FILE *f, int *NumOfParts)
  148. {
  149.     int LineNum = 0;
  150.     char Line[LINE_LEN], *p, *Name, *Prefix;
  151.     BooleanType Res, HasLines;
  152.     PriorQue
  153.     *PQ = NULL;
  154.     LibraryEntryStruct *LibEntry;
  155.  
  156.     *NumOfParts = 0;
  157.  
  158.     if (GetLine(f, Line, &LineNum) == NULL ||
  159.     strncmp(Line, FILE_IDENT, sizeof(FILE_IDENT) - 1) != 0) {
  160.     FatalError("File is NOT EEDRAW library!");
  161.     }
  162.  
  163.     PQInit(&PQ);
  164.     PQCompFunc((PQCompFuncType) LibraryEntryCompare);
  165.  
  166.     while (GetLine(f, Line, &LineNum)) {
  167.     p = strtok(Line, " \t\n");
  168.  
  169.     if (strcmp(p, "DEF") != 0) {
  170.         sprintf(Line, "DEF command expected in line %d, aborted.",
  171.                                 LineNum);
  172.         FatalError(Line);
  173.     }
  174.     else {
  175.         /* Read one DEF/ENDDEF part entry from library: */
  176.         LibEntry = (LibraryEntryStruct *)
  177.                     MyMalloc(sizeof(LibraryEntryStruct));
  178.         LibEntry -> BBoxMinX = LibEntry -> BBoxMaxX =
  179.         LibEntry -> BBoxMinY = LibEntry -> BBoxMaxY = 0;
  180.         LibEntry -> Pins = NULL;
  181.         LibEntry -> Drawings = NULL;
  182.         LibEntry -> Multi = NULL;
  183.  
  184.         if ((Name = strtok(NULL, " \t\n")) == NULL ||      /* Part name: */
  185.         (Prefix = strtok(NULL, " \t\n")) == NULL ||  /* Prefix name: */
  186.         (p = strtok(NULL, " \t\n")) == NULL ||         /* NumOfPins: */
  187.         sscanf(p, "%d", &LibEntry -> NumOfPins) != 1 ||
  188.         (p = strtok(NULL, " \t\n")) == NULL ||        /* TextInside: */
  189.         sscanf(p, "%d", &LibEntry -> TextInside) != 1 ||
  190.         (p = strtok(NULL, " \t\n")) == NULL ||            /* DrawNums: */
  191.         sscanf(p, "%d", &LibEntry -> DrawNums) != 1 ||
  192.         (p = strtok(NULL, " \t\n")) == NULL ||        /* NumOfUnits: */
  193.         sscanf(p, "%d", &LibEntry -> NumOfUnits) != 1 ||
  194.         (LibEntry -> NumOfUnits > 0 &&
  195.          ((p = strtok(NULL, " \t\n")) == NULL ||     /* PinsPerUnit: */
  196.            sscanf(p, "%d", &LibEntry -> PinsPerUnit) != 1)) ||
  197.         strlen(Name) > PART_NAME_LEN ||
  198.         strlen(Prefix) > PREFIX_NAME_LEN) {
  199.         sprintf(Line, "Wrong DEF format in line %d, aborted.",
  200.                                 LineNum);
  201.         FatalError(Line);
  202.         }
  203.         else {
  204.         /* Copy part name and prefix. */
  205.         strupr(Name);
  206.         if ((LibEntry -> DrawName = Name[0] != '~') != FALSE)
  207.             strcpy(LibEntry -> Name, Name);
  208.         else
  209.             strcpy(LibEntry -> Name, &Name[1]);
  210.         if (strcmp(Prefix, "~") == 0)
  211.             LibEntry -> Prefix[0] = 0;
  212.         else
  213.             strcpy(LibEntry -> Prefix, Prefix);
  214.         }
  215.  
  216.         HasLines = FALSE;
  217.         while (TRUE) {
  218.         GetLine(f, Line, &LineNum);
  219.         p = strtok(Line, " \t\n");
  220.  
  221.         Res = TRUE;
  222.         if (strcmp(p, "ENDDEF") == 0) {
  223.             ++*NumOfParts;
  224.             break;
  225.         }
  226.         else if (strcmp(p, "DRAW") == 0)
  227.             Res = (LibEntry -> Drawings =
  228.                GetDrawEntry(f, Line, &LineNum, &HasLines,
  229.                                LibEntry)) != NULL;
  230.         else if (strcmp(p, "PINS") == 0)
  231.             Res = (LibEntry -> Pins =
  232.                GetPinsEntry(f, Line, &LineNum,
  233.                     LibEntry -> NumOfPins)) != NULL;
  234.         else if (strcmp(p, "MULTI") == 0) {
  235.             if (LibEntry -> NumOfUnits > 0)
  236.             Res = (LibEntry -> Multi =
  237.                    GetMultiEntry(f, Line, &LineNum,
  238.                          LibEntry -> NumOfUnits,
  239.                          LibEntry -> PinsPerUnit)) != NULL;
  240.             else {
  241.             sprintf(Line, "MULTI found in DEF with #Units = 0 in line %d, aborted.",
  242.                                 LineNum);
  243.             FatalError(Line);
  244.             }
  245.         }
  246.         else {
  247.             sprintf(Line, "Undefined command \"%s\" in line %d, aborted.",
  248.                                 p, LineNum);
  249.             FatalError(Line);
  250.         }
  251.  
  252.         if (!Res) {              /* Something went wrong there. */
  253.             FatalError("Wrong format");        /* Should die before! */
  254.         }
  255.         }
  256.         if (LibEntry -> Pins == NULL && HasLines) {
  257.         sprintf(Line, "No PINS defined for part in line %d, aborted.",
  258.                                 LineNum);
  259.         FatalError(Line);
  260.         }
  261.         if (LibEntry -> NumOfUnits > 0) {
  262.         if (LibEntry -> Multi == NULL) {
  263.             sprintf(Line, "No MULTI defined for part in line %d, aborted.",
  264.                                 LineNum);
  265.             FatalError(Line);
  266.         }
  267.         if (LibEntry -> Drawings == NULL) {
  268.             sprintf(Line, "No DRAW defined for part in line %d, aborted.",
  269.                                 LineNum);
  270.             FatalError(Line);
  271.         }
  272.         }
  273.         if (LibEntry -> Drawings == NULL) {
  274.         /* Initialize BBox manually - its only a box with pins: */
  275.         LibEntry -> BBoxMaxX = LibEntry -> BBoxMaxY =
  276.            PIN_WIDTH * LibEntry -> NumOfPins / 2 + PIN_LENGTH;
  277.         LibEntry -> BBoxMinX = LibEntry -> BBoxMinY =
  278.             -LibEntry -> BBoxMaxX;
  279.         }
  280.  
  281.         /* If we are here, this part is O.k. - put it in: */
  282.         PQInsert(&PQ, (VoidPtr) LibEntry);
  283.     }
  284.     }
  285.  
  286.     return PQ;
  287. }
  288.  
  289. /*****************************************************************************
  290. * Routine to load a PINS definition from given file. Note "PINS" line has    *
  291. * been read already. Reads upto and include ENDPINS, or an error (NULL ret). *
  292. *****************************************************************************/
  293. static char *GetPinsEntry(FILE *f, char *Line, int *LineNum, int NumOfPins)
  294. {
  295.     int i;
  296.     char *p, Pins[LINE_LEN];
  297.  
  298.     Pins[0] = 0;
  299.     for (i = 0; i < NumOfPins; i++) {
  300.     if (GetLine(f, Line, LineNum) == NULL) {
  301.         FatalError("File ended prematurely");
  302.     }
  303.  
  304.     p = strtok(Line, "\n");             /* Remove the CR from line end. */
  305.     if (strcmp(p, "ENDPINS") == 0) {
  306.         sprintf(Line, "ENDPINS too soon (not enough pins) in line %d, aborted.", *LineNum);
  307.         FatalError(Line);
  308.     }
  309.     if ((p[0] == '~' && strlen(p) == 1))           /* Empty line ("~") ? */
  310.         strcat(Pins, "~");
  311.     else
  312.         strcat(Pins, p);
  313.     strcat(Pins, PIN_SEPERATOR);
  314.     if (strlen(Pins) > LINE_LEN - 10) {
  315.         sprintf(Line, "Pin definitions are too long in line %d, aborted.",
  316.                                 *LineNum);
  317.         FatalError(Line);
  318.     }
  319.     }
  320.  
  321.     if (GetLine(f, Line, LineNum) == NULL) {
  322.     FatalError("File ended prematurely");
  323.     }
  324.     p = strtok(Line, " \t\n");
  325.     if (strcmp(p, "ENDPINS") != 0) {
  326.     sprintf(Line, "ENDPINS expected in line %d, aborted.", *LineNum);
  327.     FatalError(Line);
  328.     }
  329.  
  330.     return strdup(Pins);
  331. }
  332.  
  333. /*****************************************************************************
  334. * Routine to load a MULTI definition from given file. Note "MULTI" line has  *
  335. * been read already. Reads upto and include ENDMULTI, or an error (NULL ret).*
  336. *****************************************************************************/
  337. static int *GetMultiEntry(FILE *f, char *Line, int *LineNum, int NumOfUnits,
  338.                             int PinsPerUnit)
  339. {
  340.     int i, j, *Array,
  341.     Count = 0;
  342.     char *p;
  343.  
  344.     Array = (int *) MyMalloc(sizeof(int) * NumOfUnits * PinsPerUnit);
  345.  
  346.     for (i = 0; i < NumOfUnits; i++) {
  347.     if (GetLine(f, Line, LineNum) == NULL) {
  348.         FatalError("File ended prematurely");
  349.     }
  350.  
  351.     for (p = strtok(Line, " \t\n"), j = 0;
  352.          j < PinsPerUnit;
  353.          p = strtok(NULL, " \t\n"), j++) {
  354.         if (p == NULL ||
  355.         sscanf(p, "%d", &Array[Count++]) != 1) {
  356.         sprintf(Line, "MULTI has less pins than needed in line %d",
  357.                                 *LineNum);
  358.         FatalError(Line);
  359.         }
  360.     }
  361.     }
  362.  
  363.     if (GetLine(f, Line, LineNum) == NULL) {
  364.     FatalError("File ended prematurely");
  365.     }
  366.     p = strtok(Line, " \t\n");
  367.     if (strcmp(p, "ENDMULTI") != 0) {
  368.     sprintf(Line, "ENDMULTI expected in line %d, aborted.", *LineNum);
  369.     FatalError(Line);
  370.     }
  371.  
  372.     return Array;
  373. }
  374.  
  375. /*****************************************************************************
  376. * Routine to load a DRAW definition from given file. Note "DRAW" line has    *
  377. * been read already. Reads upto and include ENDDRAW, or an error (NULL ret). *
  378. *****************************************************************************/
  379. static LibraryDrawEntryStruct *GetDrawEntry(FILE *f, char *Line, int *LineNum,
  380.             BooleanType *HasLines, LibraryEntryStruct *LibEntry)
  381. {
  382.     int i;
  383.     char *p, Buffer[LINE_LEN_SHORT];
  384.     RealType r;
  385.     BooleanType
  386.     Error = FALSE;
  387.     LibraryDrawEntryStruct *Tail, *New,
  388.     *Head = NULL;
  389.  
  390.     HasLines = FALSE;
  391.  
  392.     while (TRUE) {
  393.     if (GetLine(f, Line, LineNum) == NULL) {
  394.         FatalError("File ended prematurely");
  395.     }
  396.  
  397.     if (strncmp(Line, "ENDDRAW", 7) == 0) break;
  398.  
  399.     New = (LibraryDrawEntryStruct *)
  400.                 MyMalloc(sizeof(LibraryDrawEntryStruct));
  401.     New -> Pnext = NULL;
  402.  
  403.     switch (Line[0]) {
  404.         case 'A': /* Arc */
  405.         New -> DrawType = ARC_DRAW_TYPE;
  406.         Error = sscanf(&Line[2], "%d %d %d %d %d %d", &New->Layer,
  407.             &New -> U.Arc.x, &New -> U.Arc.y, &New -> U.Arc.r,
  408.             &New -> U.Arc.t1, &New -> U.Arc.t2) != 6;
  409.         New ->U.Arc.x *= LIB_SCALE_DRAW;
  410.         New ->U.Arc.y *= LIB_SCALE_DRAW;
  411.         New ->U.Arc.r *= LIB_SCALE_DRAW;
  412.         NORMALIZE_ANGLE(New -> U.Arc.t1);
  413.         NORMALIZE_ANGLE(New -> U.Arc.t2);
  414.         if (New -> U.Arc.t1 > New -> U.Arc.t2)
  415.             New -> U.Arc.t2 += 360;
  416.         New -> U.Arc.t1 += 1; /* Force arc of 180 degree to be less. */
  417.         New -> U.Arc.t2 -= 1;
  418.  
  419.         /* Update the bbox: */
  420.         UpdateBBox(LibEntry, New -> U.Arc.x - New -> U.Arc.r,
  421.                      New -> U.Arc.y - New -> U.Arc.r);
  422.         UpdateBBox(LibEntry, New -> U.Arc.x + New -> U.Arc.r,
  423.                      New -> U.Arc.y + New -> U.Arc.r);
  424.         break;
  425.         case 'C': /* Circle */
  426.         New -> DrawType = CIRCLE_DRAW_TYPE;
  427.         Error = sscanf(&Line[2], "%d %d %d %d", &New->Layer,
  428.             &New -> U.Circ.x, &New -> U.Circ.y, &New -> U.Circ.r) != 4;
  429.         New ->U.Circ.x *= LIB_SCALE_DRAW;
  430.         New ->U.Circ.y *= LIB_SCALE_DRAW;
  431.         New ->U.Circ.r *= LIB_SCALE_DRAW;
  432.         /* Update the bbox: */
  433.         UpdateBBox(LibEntry, New -> U.Circ.x - New -> U.Circ.r,
  434.                      New -> U.Circ.y - New -> U.Circ.r);
  435.         UpdateBBox(LibEntry, New -> U.Circ.x + New -> U.Circ.r,
  436.                      New -> U.Circ.y + New -> U.Circ.r);
  437.         break;
  438.         case 'T': /* Text */
  439.         New -> DrawType = TEXT_DRAW_TYPE;
  440.         Error = sscanf(&Line[2], "%d %d %d %d %s", &New->Layer,
  441.                    &New -> U.Text.x, &New -> U.Text.y,
  442.                    &New -> U.Text.Horiz, Buffer) != 5;
  443.         if (!Error) {               /* Convert '~' to spaces. */
  444.             for (i = 0; i < strlen(Buffer); i++)
  445.             if (Buffer[i] == '~') Buffer[i] = ' ';
  446.             New -> U.Text.Text = strdup(Buffer);
  447.         }
  448.         New ->U.Text.x *= LIB_SCALE_DRAW;
  449.         New ->U.Text.y *= LIB_SCALE_DRAW;
  450.         break;
  451.         case 'S': /* Square */
  452.         New -> DrawType = SQUARE_DRAW_TYPE;
  453.         Error = sscanf(&Line[2], "%d %d %d %d %d", &New->Layer,
  454.                    &New -> U.Sqr.x1, &New -> U.Sqr.y1,
  455.                    &New -> U.Sqr.x2, &New -> U.Sqr.y2) != 5;
  456.         New ->U.Sqr.x1 *= LIB_SCALE_DRAW;
  457.         New ->U.Sqr.y1 *= LIB_SCALE_DRAW;
  458.         New ->U.Sqr.x2 *= LIB_SCALE_DRAW;
  459.         New ->U.Sqr.y2 *= LIB_SCALE_DRAW;
  460.         break;
  461.         case 'L': /* Line */
  462.         *HasLines = TRUE;
  463.         New -> DrawType = LINE_DRAW_TYPE;
  464.         if ((i = sscanf(&Line[2], "%d %d %d %d %d %s",&New->Layer,
  465.                 &New -> U.Line.x1, &New -> U.Line.y1,
  466.                 &New -> U.Line.x2, &New -> U.Line.y2,
  467.                 Buffer)) != 6)
  468.             i = sscanf(&Line[2], "%d %d %d %d %d",&New->Layer,
  469.                    &New -> U.Line.x1, &New -> U.Line.y1,
  470.                    &New -> U.Line.x2, &New -> U.Line.y2);
  471.         Error = (i != 5 && i != 6) ||
  472.             (New -> U.Line.x1 != New -> U.Line.x2 &&
  473.              New -> U.Line.y1 != New -> U.Line.y2);
  474.         New ->U.Line.x1 *= LIB_SCALE_DRAW;
  475.         New ->U.Line.y1 *= LIB_SCALE_DRAW;
  476.         New ->U.Line.x2 *= LIB_SCALE_DRAW;
  477.         New ->U.Line.y2 *= LIB_SCALE_DRAW;
  478.         UpdateBBox(LibEntry, New -> U.Line.x1, New -> U.Line.y1);
  479.         UpdateBBox(LibEntry, New -> U.Line.x2, New -> U.Line.y2);
  480.         New -> U.Line.Invert = i == 5 && Buffer[0] == 'I';
  481.         break;
  482.         case 'P': /* Polyline */
  483.         New -> DrawType = POLYLINE_DRAW_TYPE;
  484.         New -> U.Poly.PolyList = NULL;
  485.         p = strtok(&Line[4], " \t\n");
  486.         if (sscanf(&Line[2], "%d %d",
  487.             &New->Layer, &New -> U.Poly.n) == 2 &&
  488.             New -> U.Poly.n > 0) {
  489.             New -> U.Poly.PolyList = (int *)
  490.             MyMalloc(sizeof(int) * New -> U.Poly.n * 2);
  491.             for (i = 0; i < New -> U.Poly.n * 2 && !Error; i++) {
  492.             p = strtok(NULL, " \t\n");
  493.             Error = sscanf(p, "%d", &New -> U.Poly.PolyList[i]) !=
  494.                                     1;
  495.             New ->U.Poly.PolyList[i] *= LIB_SCALE_DRAW;
  496.             if (i % 2 != 0)
  497.                 UpdateBBox(LibEntry, New -> U.Poly.PolyList[i-1],
  498.                          New -> U.Poly.PolyList[i]);
  499.             }
  500.             New -> U.Poly.Fill = (p = strtok(NULL, " \t\n")) != NULL &&
  501.                      p[0] == 'F';
  502.         }
  503.         else
  504.             Error = TRUE;
  505.         Error |= New -> U.Poly.Fill &&
  506.             (New -> U.Poly.PolyList[0] != New -> U.Poly.PolyList[i-2] ||
  507.              New -> U.Poly.PolyList[1] != New -> U.Poly.PolyList[i-1]);
  508.         if (Error && New -> U.Poly.PolyList)
  509.             MyFree((VoidPtr) New -> U.Poly.PolyList);
  510.         break;
  511.         default:
  512.         sprintf(Line, "Undefined DRAW command in line %d, aborted.",
  513.                                 *LineNum);
  514.         FatalError(Line);
  515.     }
  516.     if (Error) {
  517.         sprintf(Line, "Error in %c DRAW command in line %d, aborted.",
  518.                             Line[0], *LineNum);
  519.         FatalError(Line);
  520.     }
  521.     else {
  522.         if (Head == NULL)
  523.         Head = Tail = New;
  524.         else {
  525.         Tail -> Pnext = New;
  526.         Tail = New;
  527.         }
  528.     }
  529.     }
  530.  
  531.     /* Update the bbox to the maximum extrem as we may rotate the object. */
  532.     r = MAX(ABS(LibEntry->BBoxMinX), ABS(LibEntry->BBoxMaxX));
  533.     r = MAX(r, ABS(LibEntry->BBoxMinY));
  534.     r = MAX(r, ABS(LibEntry->BBoxMaxY));
  535.     LibEntry->BBoxMaxX = LibEntry->BBoxMaxY = r;
  536.     LibEntry->BBoxMinX = LibEntry->BBoxMinY = -r;
  537.  
  538.     return Head;
  539. }
  540.  
  541. /*****************************************************************************
  542. * Routine to update LibEntry bounding box accrding to given x, y value.         *
  543. *****************************************************************************/
  544. static void UpdateBBox(LibraryEntryStruct *LibEntry, int x, int y)
  545. {
  546.     if (LibEntry -> BBoxMinX > x) LibEntry -> BBoxMinX = x;
  547.     if (LibEntry -> BBoxMaxX < x) LibEntry -> BBoxMaxX = x;
  548.     if (LibEntry -> BBoxMinY > y) LibEntry -> BBoxMinY = y;
  549.     if (LibEntry -> BBoxMaxY < y) LibEntry -> BBoxMaxY = y;
  550. }
  551.  
  552. /*****************************************************************************
  553. * Routine to find the library given its name.                     *
  554. *****************************************************************************/
  555. static LibraryStruct *FindLibrary(char *Name)
  556. {
  557.     LibraryStruct
  558.     *Lib = LibraryList;
  559.  
  560.     while (Lib) {
  561.     if (strcmp(Name, Lib -> Name) == 0) return Lib;
  562.     Lib = Lib -> Pnext;
  563.     }
  564.     return NULL;
  565. }
  566.  
  567. #ifndef __MSDOS__
  568.  
  569. /*****************************************************************************
  570. * Routine to convert a string to all upper case:                 *
  571. *****************************************************************************/
  572. char *strupr(char *s)
  573. {
  574.     while (*s) {
  575.     if (islower(*s)) *s = toupper(*s);
  576.     s++;
  577.     }
  578.  
  579.     return s;
  580. }
  581.  
  582. /*****************************************************************************
  583. * Routine to convert a string to all upper case:                 *
  584. *****************************************************************************/
  585. char *strlwr(char *s)
  586. {
  587.     while (*s) {
  588.     if (isupper(*s)) *s = tolower(*s);
  589.     s++;
  590.     }
  591.  
  592.     return s;
  593. }
  594.  
  595. #endif /* __MSDOS__ */
  596.